package org.dromara.system.service.impl;

import lombok.RequiredArgsConstructor;
import org.dromara.system.domain.vo.DeviceGroupVo;
import org.dromara.system.mapper.DeviceGroupMapper;
import org.dromara.system.mapper.DeviceUserGroupMapper;
import org.dromara.system.service.IDeviceUserGroupService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设备变量关联Service业务层处理
 *
 * @author Lion Li
 * @date 2024-10-22
 */
@RequiredArgsConstructor
@Service
public class DeviceUserGroupServiceImpl implements IDeviceUserGroupService {

    private final DeviceUserGroupMapper baseMapper;
    private final DeviceGroupMapper deviceGroupMapper;


    @Override
    public List<DeviceGroupVo> getGroupList(Long userId) {
        List<Long> selectedIds = baseMapper.selectGroupIdListByUserId(userId);
        List<DeviceGroupVo> allNodes = deviceGroupMapper.selectVoList();
        Map<Long, DeviceGroupVo> idToNodeMap = allNodes.stream()
                .collect(Collectors.toMap(DeviceGroupVo::getId, node -> node));

        // 从目标节点集合向上追溯到顶级节点
        List<DeviceGroupVo> topNodes = traceToTopNodes(selectedIds, idToNodeMap);

        // 重新构建树结构
        return buildTree(topNodes, idToNodeMap);

    }

    private List<DeviceGroupVo> traceToTopNodes(List<Long> selectedIds, Map<Long, DeviceGroupVo> idToNodeMap) {
        List<DeviceGroupVo> relatedNodes = new ArrayList<>();
        for (Long selectedId : selectedIds) {
            DeviceGroupVo currentNode = idToNodeMap.get(selectedId);
            if (currentNode == null) {
                continue;
            }
            while (currentNode != null) {
                if (!relatedNodes.contains(currentNode)) {
                    relatedNodes.add(currentNode);
                }
                if (currentNode.getParentId() == null) {
                    break;
                }
                currentNode = idToNodeMap.get(currentNode.getParentId());
            }
        }
        return relatedNodes;
    }


    private List<DeviceGroupVo> buildTree(List<DeviceGroupVo> nodes, Map<Long, DeviceGroupVo> idToNodeMap) {
        Map<Long, DeviceGroupVo> nodeMap = new HashMap<>();
        for (DeviceGroupVo node : nodes) {
            nodeMap.put(node.getId(), node);
        }

        List<DeviceGroupVo> roots = new ArrayList<>();
        for (DeviceGroupVo node : nodes) {
            if (node.getParentId() == null || !nodeMap.containsKey(node.getParentId())) {
                roots.add(node);
            } else {
                DeviceGroupVo parent = nodeMap.get(node.getParentId());
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(node);
            }
        }
        return roots;
    }


}
